// -------------------------------------------------
// BlinKit - BlinKit Library
// -------------------------------------------------
//   File Name: qjs_base64.cpp
// Description: Bindings for Base64
//      Author: Ziming Li
//     Created: 2022-03-04
// -------------------------------------------------
// Copyright (C) 2022 MingYang Software Technology.
// -------------------------------------------------

#include "./qjs_bindings.h"

#include "blinkit/blink/renderer/bindings/core/qjs/qjs_c_function_list_entries.h"
#include "blinkit/blink/renderer/wtf/text/Base64.h"

namespace BlinKit {
namespace qjs {

static const char kStringRequired[] = "String required";

static JSValue AToB(JSContext *ctx, JSValueConst thisVal, int argc, JSValueConst *argv)
{
    if (!JS_IsString(argv[0]))
        return JS_ThrowTypeError(ctx, kStringRequired);

    JSValue ret;
    Vector<char> decoded;

    size_t len;
    const char *ps = JS_ToCStringLen(ctx, &len, argv[0]);
    if (base64Decode(ps, len, decoded))
        ret = JS_NewStringLen(ctx, decoded.data(), decoded.size());
    else
        ret = JS_ThrowTypeError(ctx, "Invalid base64 string!"); // BKTODO: Throw a DOMException of InvalidCharacterError 
    JS_FreeCString(ctx, ps);

    return ret;
}

static JSValue BToA(JSContext *ctx, JSValueConst thisVal, int argc, JSValueConst *argv)
{
    if (!JS_IsString(argv[0]))
        return JS_ThrowTypeError(ctx, kStringRequired);

    Vector<char> ret;

    size_t len;
    const char *ps = JS_ToCStringLen(ctx, &len, argv[0]);
    base64Encode(ps, len, ret);
    JS_FreeCString(ctx, ps);

    return JS_NewStringLen(ctx, ret.data(), ret.size());
}

void AddBase64(JSContext *ctx, JSValue global)
{
    static const JSCFunctionListEntry GlobalFuncs[] = {
        CFunctionEntry("atob", 1, AToB),
        CFunctionEntry("btoa", 1, BToA)
    };
    JS_SetPropertyFunctionList(ctx, global, GlobalFuncs, std::size(GlobalFuncs));
}

} // namespace qjs
} // namespace BlinKit
